from django.contrib.auth.hashers import make_password, check_password
from rest_framework.pagination import PageNumberPagination
from rest_framework_simplejwt.exceptions import TokenError
from rest_framework_simplejwt.tokens import RefreshToken

from apps.common.redis_opration import Redis_SMS_Operator
from apps.common.send_sms import get_code,send_sms_code
from apps.system.filters import  OperationRecordFilter, LoginLogFilter
from apps.system.md5 import decode
from apps.system.models import Region, OperationRecord, Organization
from apps.system.schemas import SMSGetTokenRequest, SMSRequest
from apps.system.serializers import RegionsSerializer, OperationRecordSerializer, LoginLogSerializer, \
    OrganizationSerializer
from configs.sms_4A import SEND_SMS_METHOD, APP_ID, APP_ID_Evaluation
from extensions.common.schema import *
from extensions.common.base import *
from extensions.permissions import *
from extensions.exceptions import *
from extensions.viewsets import *
from apps.system.serializers import *
from apps.system.schemas import *
from apps.system.models import *
from apps.common.com import Pagination
from rest_framework import status, filters


class PaginationCls(PageNumberPagination):
    page_size = 15
    page_size_query_param = 'page_size'
    page_query_param = 'page'
    max_page_size = 100000

#选项分页
class OptionPaginationCls(PageNumberPagination):
    page_size = 99999
    page_size_query_param = 'page_size'
    page_query_param = 'page'
    max_page_size = 100000

class PermissionGroupViewSet(BaseViewSet, ListModelMixin):
    """权限分组"""

    serializer_class = PermissionGroupSerializer
    permission_classes = [IsAuthenticated]
    pagination_class = None
    ordering = ['id']
    queryset = PermissionGroup.objects.all()

    def get_queryset(self):
        return self.queryset.prefetch_related('permissions').all()

class SystemConfigViewSet(BaseViewSet, ListModelMixin):
    """权限分组"""

    serializer_class = PermissionGroupSerializer
    permission_classes = [IsAuthenticated]
    pagination_class = None
    ordering = ['id']
    queryset = PermissionGroup.objects.all()

    def get_queryset(self):
        return self.queryset.prefetch_related('permissions').all()


class RoleViewSet(ModelViewSet):
    """角色"""

    serializer_class = RoleSerializer
    permission_classes = [IsAuthenticated, IsManagerPermission]
    pagination_class = Pagination
    search_fields = ['name']
    queryset = Role.objects.all()

    @transaction.atomic
    def perform_update(self, serializer):
        role = serializer.save()

        # 同步用户权限
        users = role.users.prefetch_related('roles', 'roles__permissions').all()
        for user in users:
            permissions = {permission.code for role in user.roles.all()
                           for permission in role.permissions.all()}
            user.permissions = list(permissions)
        else:
            User.objects.bulk_update(users, ['permissions'])

    @transaction.atomic
    def perform_destroy(self, instance):
        users = instance.users.all()
        instance.delete()

        # 同步用户权限
        for user in users.prefetch_related('roles', 'roles__permissions').all():
            permissions = {permission.code for role in user.roles.all()
                           for permission in role.permissions.all()}
            user.permissions = list(permissions)
        else:
            User.objects.bulk_update(users, ['permissions'])


class OperationRecordsPagination(PageNumberPagination):
    page_size = 15
    page_size_query_param = 'page_size'
    page_query_param = 'current'
    max_page_size = 100000


class OperationRecordsViewSet(ModelViewSet):
    """操作日志"""
    serializer_class = OperationRecordSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    permission_classes = [IsAuthenticated]
    pagination_class = OperationRecordsPagination
    filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
    filter_class = OperationRecordFilter
    search_fields = ['user__name','url_name']
    ordering_fields = ['id','create_time']
    queryset = OperationRecord.objects.filter(del_flag=False)


class LoginLogsViewSet(ModelViewSet):
    """登录日志"""
    serializer_class = LoginLogSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    permission_classes = [IsAuthenticated]
    pagination_class = OperationRecordsPagination
    filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
    filter_class = LoginLogFilter
    search_fields = ['user__name','ip_address','user_agent']
    ordering_fields = ['id','create_time']
    queryset = LoginLog.objects.all()


class JobsViewSet(ModelViewSet):
    """职务"""
    serializer_class = JobsSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    # permission_classes = [IsAuthenticated]
    pagination_class = PaginationCls
    search_fields = ['name']
    ordering_fields = ['id','name','index']
    queryset = Job.objects.all()


class DictsViewSet(ModelViewSet):
    """职务"""
    serializer_class = DictsSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    # permission_classes = [IsAuthenticated]
    pagination_class = OptionPaginationCls
    search_fields = ['name']
    ordering_fields = ['id','name',]
    queryset = Dict.objects.all()

    def get_queryset(self):
        qs = super().get_queryset()
        sys_name = self.request.GET.get('sys_name', None)  # 获取前端传来的sys_name参数
        if sys_name:
            qs = qs.filter(id__contains=sys_name) # 过滤出id包含sys_name的Dict对象
        return qs.prefetch_related('dict_item').order_by('dict_item__index')


class RegionsViewSet(ModelViewSet):
    serializer_class = RegionsSerializer
    pagination_class = PaginationCls
    search_fields = ['name']
    ordering_fields = ['id','name','index']
    queryset = Region.objects.all()
    #把数据组装成市、区县的列表格式
    def list(self, request):
        queryset = self.filter_queryset(self.get_queryset())
        serializer = self.get_serializer(queryset, many=True)
        # print(len(serializer.data))
        # 遍历出每个order item
        quxians =[]
        for item in serializer.data:
            if item['region_level']==2:
                children = []
                for quxian in serializer.data:
                    if item['id']==quxian['region_parent_id']:
                        quxian['value'] = quxian['id']
                        quxian['label'] = quxian['region_name']
                        quxian.pop('id')
                        quxian.pop('region_name')
                        children.append(quxian)
                    item['children']=children
                item['value']=item['id']
                item['label']=item['region_name']
                item.pop('id')
                item.pop('region_name')
                quxians.append(item)
            # 将order中的'sales_goods_items'中的'clAmount'、'jgAmount'进行求和clAmount_sum、jgAmount_sum
        print(quxians)
        data={
            "results":quxians
        }
        return Response(data=data, status=status.HTTP_200_OK)


class UserViewSet(ModelViewSet):
    """用户"""

    serializer_class = UserSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    pagination_class = Pagination
    filterset_fields = ['is_active']
    search_fields = ['username', 'name', 'phone', 'email']
    ordering_fields = ['id', 'username', 'name']
    queryset = User.objects.all()

    def perform_destroy(self, instance):
        if instance.is_manager:
            raise ValidationError('无法删除管理员账号')

        try:
            instance.delete()
        except ProtectedError:
            raise ValidationError(f'用户[{instance.username}]已被引用, 无法删除')

    @extend_schema(request=None, responses={200: None})
    @action(detail=True, methods=['post'])
    def reset_password(self, request, *args, **kwargs):
        """重置密码"""

        instance = self.get_object()
        instance.password = make_password(self.user.username)
        instance.save(update_fields=['password'])

        return Response(status=status.HTTP_200_OK)


class OrganizationViewSet(ModelViewSet):
    """组织"""

    serializer_class = OrganizationSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    pagination_class = Pagination
    filterset_fields = ['name']
    search_fields = ['name']
    ordering_fields = ['index']
    queryset = Organization.objects.all()

    def get_queryset(self):
        # 只获取没有父组织的组织
        return Organization.objects.filter(parent__isnull=True)




class UserActionViewSet(FunctionViewSet):
    """用户操作"""
    # 发送短信验证码 18308576111
    # @extend_schema(request=None, responses={200: None})
    @extend_schema(request=SMSRequest, responses={200: GetTokenResponse})
    @action(detail=False, methods=['post'])
    def send_sms(self, request, *args, **kwargs):
        serializer = SMSRequest(data=request.data)
        serializer.is_valid(raise_exception=True)
        validated_data = serializer.validated_data
        phone_num=decode(validated_data['mobile'],'mobile')
        if not (user := User.objects.filter(phone=phone_num).first()):
            raise ValidationError('用户不存在')
        try:
            #             """
            #             查看redis中是否存在该手机号码，
            #             1、如果有则提示该验证码还在有效期内
            #             2、如果没有则发送新的验证码
            #             """
            sms_operator = Redis_SMS_Operator()
            key_value = sms_operator.get_key_value(phone_num)
            if key_value:
                resp = {"code": 40001, "flag": False, "message": '动态密码仍在有效期内，请查看手机短信获取！'}
            else:
                code = get_code()
                res = send_sms_code(phone_num, code)
                if res['Code'] == 'OK':
                    # 将验证码存到Redis
                    sms_operator = Redis_SMS_Operator()
                    sms_operator.add_key_value(phone_num, code)
                    resp = {"code": 20000, "flag": True, "message": "动态密码发送成功！", "result": res}
                else:
                    resp = {"code": 40000, "flag": False, "message": "动态密码发送失败，请检查手机号码是否正确！", "aly_res": res}
        except Exception as e:
            print(e)
            resp = {"code": 40001, "flag": False, "message": "获取验证码失败，您尚未注册！"}
        return Response(resp)

    # 短信验证码版
    @extend_schema(request=GetTokenRequest, responses={200: GetTokenResponse})
    @action(detail=False, methods=['post'])
    def get_token(self, request, *args, **kwargs):
        """获取令牌"""
        serializer = SMSGetTokenRequest(data=request.data)
        serializer.is_valid(raise_exception=True)
        validated_data = serializer.validated_data
        mobile = decode(validated_data['mobile'], 'mobile')
        sys_name = validated_data['sys_name']
        if not (user := User.objects.filter(phone=mobile).first()):
            raise ValidationError('用户不存在')
        code = decode(validated_data['code'], 'code')
        try:
            #根据mobile获取Redis对应的键值
            sms_operator = Redis_SMS_Operator()
            result = sms_operator.get_key_value(mobile)
            if result is not None:
                code_from_redis = str(result, encoding='utf-8')
                if code == code_from_redis:
                    token = RefreshToken()
                    ip_address = request.META.get('REMOTE_ADDR')
                    user_agent = request.META.get('HTTP_USER_AGENT')
                    login_log = LoginLog(user=user, ip_address=ip_address, user_agent=user_agent)
                    login_log.save()
                    token['user_id'] = user.id
                    data = {'refresh': str(token), 'access': str(token.access_token)}
                    sms_operator.del_key_value(mobile)
                    return Response(data=data, status=status.HTTP_200_OK)
                else:
                    resp = {"code": 40001, "flag": False, "message": '手机号码或动态密码错误！'}
            else:
                resp = {"code": 40008, "flag": False, "message": '请先获取动态密码！'}
            return Response(resp)
        except Exception as e:
            print(e)
            resp = {"code": 40001, "flag": False, "message": '手机号码或动态密码错误！'}
            return Response(resp)

        if not user.is_active and not user.is_manager:
            raise ValidationError('用户未激活')
        # 免验证码版，为了方便测试
        if not user.is_active and not user.is_manager:
            raise ValidationError('用户未激活')
        token = RefreshToken()
        # user = request.user
        ip_address = request.META.get('REMOTE_ADDR')
        user_agent = request.META.get('HTTP_USER_AGENT')
        login_log = LoginLog(user=user, ip_address=ip_address, user_agent=user_agent)
        login_log.save()
        token['user_id'] = user.id
        data = {'refresh': str(token), 'access': str(token.access_token)}

        return Response(data=data, status=status.HTTP_200_OK)


    @extend_schema(request=RefreshTokenRequest, responses={200: RefreshTokenResponse})
    @action(detail=False, methods=['post'])
    def refresh_token(self, request, *args, **kwargs):
        """刷新令牌"""

        serializer = RefreshTokenRequest(data=request.data)
        serializer.is_valid(raise_exception=True)
        validated_data = serializer.validated_data

        try:
            token = RefreshToken(validated_data['refresh'])
        except TokenError:
            raise NotAuthenticated('令牌失效')

        data = {'access': str(token.access_token)}
        return Response(data=data, status=status.HTTP_200_OK)

    @extend_schema(responses={200: UserInfoResponse})
    @action(detail=False, methods=['get'], permission_classes=[IsAuthenticated])
    def info(self, request, *args, **kwargs):
        """用户信息"""

        serializer = UserInfoResponse(instance=self.user)
        return Response(data=serializer.data, status=status.HTTP_200_OK)



__all__ = [
    'PermissionGroupViewSet',
    'SystemConfigViewSet',
    'JobsViewSet',
    'DictsViewSet',
    'RoleViewSet', 'UserViewSet', 'UserActionViewSet',

]
